#include "config.h"

#include "edb.h"
#include "ecmconf.h"

static ECMBOOL
check_ebcd_sanity(sr_t *sr_conf)
{
	ecm_ebc_t	ebc;
	ecm_uint16	ebc_port;
	int	retry = 0;

	ebc_port = (ecm_uint16)sr_getc_int(sr_conf, "ebc_port");
	while (retry++ < 3) {
		if (ebc_connect(NULL, ebc_port, NULL, 5000, &ebc) != EBC_OK) {
			ecm_sleep(700);
		}
		else {
			ebc_close(ebc);
			return ECM_TRUE;
		}
	}
	return ECM_FALSE;
}

static ECMBOOL
check_edbd_sanity(sr_t *sr_conf)
{
	edb_t	*edb;
	int	retry = 0;
	ecm_uint16	ebc_port;

	ebc_port = (ecm_uint16)sr_getc_int(sr_conf, "ebc_port");
	while (retry < 3) {
		edb_err_t	err;

		if ((err = edb_connect(NULL, ebc_port, NULL, NULL, &edb)) != EDB_OK) {
			retry++;
			ecm_sleep(700);
		}
		else {
			edb_close(edb);
			return ECM_TRUE;
		}
	}
	return ECM_FALSE;
}

static ECMBOOL
start_ECM_services(void)
{
	char	*svc_arg;
	const char	*ebcd_svcname, *edbd_svcname, *egid_svcname;

	ecm_asprintf(&svc_arg, "-D -H \"%s\"", ecm_default_clxdir());

	ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");
	edbd_svcname = sr_getn1_str(sr_conf, "edbd/svcname");
	egid_svcname = sr_getn1_str(sr_conf, "egid/svcname");

	if (start_service("ebcd", ebcd_svcname, svc_arg) &&
	    start_service("edbd", edbd_svcname, svc_arg) &&
	    start_service("egid", egid_svcname, svc_arg)) {
		ecm_free(svc_arg);
		return ECM_TRUE;
	}
	ecm_free(svc_arg);
	return ECM_FALSE;
}

static ECMBOOL
stop_ECM_services(void)
{
	const char	*ebcd_svcname, *edbd_svcname, *egid_svcname;

	ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");
	edbd_svcname = sr_getn1_str(sr_conf, "edbd/svcname");
	egid_svcname = sr_getn1_str(sr_conf, "egid/svcname");

	if (stop_service("egid", egid_svcname) &&
	    stop_service("edbd", edbd_svcname) &&
	    stop_service("ebcd", ebcd_svcname))
		return ECM_TRUE;
	return ECM_FALSE;
}

static ECMBOOL
install_ECM_services(void)
{
	char		*svc_arg;
	const char	*ebcd_svcname, *edbd_svcname, *egid_svcname;
	char		*edbd_deps, *egid_deps;

	ecm_asprintf(&svc_arg, "-D -H \"%s\"", ecm_default_clxdir());

	ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");
	edbd_svcname = sr_getn1_str(sr_conf, "edbd/svcname");
	egid_svcname = sr_getn1_str(sr_conf, "egid/svcname");

	///double null termination
	ecm_asprintf(&edbd_deps, "%s%c", ebcd_svcname, '\0');
	ecm_asprintf(&egid_deps, "%s%c", edbd_svcname, '\0');

	if (install_service("ebcd", ebcd_svcname, "ECM ebcd", NULL, svc_arg) &&
	    install_service("edbd", edbd_svcname, "ECM edbd", edbd_deps, svc_arg) &&
	    install_service("egid", egid_svcname, "ECM egid", egid_deps, svc_arg)) {
		ecm_free(svc_arg);
		ecm_free(edbd_deps);
		ecm_free(egid_deps);
		return ECM_TRUE;
	}
	ecm_free(svc_arg);
	ecm_free(edbd_deps);
	ecm_free(egid_deps);

	return ECM_FALSE;
}

static ECMBOOL
remove_ECM_services(void)
{
	const char	*ebcd_svcname, *edbd_svcname, *egid_svcname;

	ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");
	edbd_svcname = sr_getn1_str(sr_conf, "edbd/svcname");
	egid_svcname = sr_getn1_str(sr_conf, "egid/svcname");

	if (remove_service("egid", egid_svcname) &&
	    remove_service("edbd", edbd_svcname) &&
	    remove_service("ebcd", ebcd_svcname))
		return ECM_TRUE;
	return ECM_FALSE;
}

int
ecmconf_install(sr_t *sr_conf)
{
	const char	*ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");

	if (is_service_started("ebcd", ebcd_svcname) && !stop_ECM_services()) {
		print_verbose("ebcd running but cannot be stopped");
		return 101;
	}

	if (!install_ECM_services()) {
		print_verbose("ECM service cannot be installed");
		return 102;
	}

	if (!start_ECM_services()) {
		print_verbose("ECM service cannot be started");
		return 103;
	}

	if (!check_ebcd_sanity(sr_conf)) {
		print_verbose("ebcd is not working");
		return 104;
	}

	if (!check_edbd_sanity(sr_conf)) {
		print_verbose("edbd is not working");
		return 105;
	}

	print_verbose("ECM service is successfully installed");
	return 0;
}

int
ecmconf_remove(void)
{
	if (!stop_ECM_services()) {
		print_verbose("ECM service cannot be stopped");
		return 101;
	}
	if (!remove_ECM_services()) {
		print_verbose("ECM service cannot be removed");
		return 102;
	}
	print_verbose("ECM service is successfully removed");
	return 0;
}

int
ecmconf_status(sr_t *sr_conf)
{
	const char	*ebcd_svcname, *edbd_svcname, *egid_svcname;

	ebcd_svcname = sr_getn1_str(sr_conf, "ebcd/svcname");
	edbd_svcname = sr_getn1_str(sr_conf, "edbd/svcname");
	egid_svcname = sr_getn1_str(sr_conf, "egid/svcname");

	if (!is_service_started("ebcd", ebcd_svcname)) {
		print_verbose("ebcd is not running");
		return 1;
	}
	if (!is_service_started("edbd", edbd_svcname)) {
		print_verbose("edbd is not running");
		return 2;
	}
	if (!is_service_started("egid", egid_svcname)) {
		print_verbose("egid is not running");
		return 3;
	}
	print_verbose("ECM service is running");
	return 0;
}
